/*
 * Permission.java
 *
 * Created on August 1, 2007, 10:03 AM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package org.atomojo.auth.service.db;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
import org.infoset.xml.Element;
import org.infoset.xml.ItemConstructor;
import org.infoset.xml.ItemDestination;
import org.infoset.xml.XMLException;
import org.milowski.db.DBConnection;
import org.milowski.db.DBObject;
import org.milowski.db.DBQueryHandler;
import org.milowski.db.DBUpdateHandler;

/**
 *
 * @author alex
 */
public class Role extends DBObject<AuthDB> implements Comparable<Role>,XMLObject
{

   String name;
   UUID uuid;
   List<Permission> permissions;
   
   /** Creates a new instance of Permission */
   public Role(AuthDB db,int id,String name,UUID uuid)
      throws SQLException
   {
      super(db,id);
      this.name = name;
      this.uuid = uuid;
      this.permissions = new ArrayList<Permission>();
      init();
   }
   
   protected void init() 
      throws SQLException
   {
      
      DBConnection connection = db.getConnection();
      try {
         connection.query(AuthDB.ROLE_PERMISSIONS, new DBQueryHandler() {
            public void prepare(PreparedStatement s)
               throws SQLException
            {
               s.setInt(1, id);
            }
            public void onResults(ResultSet set) 
               throws SQLException
            {
               while (set.next()) {
                  int pid = set.getInt(1);
                  Permission p = db.permissionCache.get(pid);
                  permissions.add(p);
               }
            }
         });
      } finally {
         db.release(connection);
      }
   }
   
   public void delete() 
      throws SQLException
   {
      DBConnection connection = db.getConnection();
      try {
         connection.deleteById(AuthDB.DELETE_ROLE_PERMISSIONS, id);
         connection.deleteById(AuthDB.DELETE_USER_ROLES_BY_ROLE, id);
         connection.deleteById(AuthDB.DELETE_GROUP_ROLES_BY_ROLE, id);
         connection.deleteById(AuthDB.DELETE_ROLE, id);
         db.realmGroupCaches.clear();
         db.roleCache.remove(id);
      } finally {
         db.release(connection);
      }
   }

   public String getName()
   {
      return name;
   }

   public UUID getUUID()
   {
      return uuid;
   }
   
   public boolean addPermission(UUID permission)
      throws SQLException
   {
      Permission p = db.getPermission(permission);
      if (p==null) {
         return false;
      }
      return addPermission(p);
   }
   
   public boolean addPermission(final Permission p) 
      throws SQLException
   {
      if (permissions.contains(p)) {
         return true;
      }
      DBConnection connection = db.getConnection();
      try {
         connection.update(AuthDB.CREATE_ROLE_PERMISSION, new DBUpdateHandler() {
            public void prepare(PreparedStatement s)
               throws SQLException
            {
               s.setInt(1, id);
               s.setInt(2, p.getId());
            }
         });
      } finally {
         db.release(connection);
      }
      permissions.add(p);
      return true;
   }
   
   public boolean removePermission(final Permission p)
      throws SQLException
   {
      DBConnection connection = db.getConnection();
      try {
         connection.update(AuthDB.DELETE_ROLE_PERMISSION, new DBUpdateHandler() {
            public void prepare(PreparedStatement s)
               throws SQLException
            {
               s.setInt(1, id);
               s.setInt(2, p.getId());
            }
         });
      } finally {
         db.release(connection);
      }
      return permissions.remove(p);
      
   }
   
   public boolean hasPermission(Permission p)
   {
      return permissions.contains(p);
   }
   
   public Iterator<Permission> getPermissions() {
      return permissions.iterator();
   }
   
   public int compareTo(Role other) {
      return uuid.compareTo(other.getUUID());
   }
   
   public boolean equals(Object obj) {
      return obj instanceof Role && ((Role)obj).getUUID().equals(uuid);
   }
   
   public void refresh() 
      throws SQLException
   {
      permissions.clear();
      init();
   }
   
   public void generate(ItemConstructor constructor,ItemDestination dest)
      throws XMLException
   {
      generate(constructor,dest,true);
   }
   
   public void generate(ItemConstructor constructor,ItemDestination dest,boolean contents)
      throws XMLException
   {
      Element top = constructor.createElement(XML.ROLE_NAME);
      top.setAttributeValue("id",uuid.toString());
      top.setAttributeValue("name",name);
      dest.send(top);
      if (contents) {
         boolean first = true;
         for (Permission p : permissions) {
            if (first) {
               dest.send(constructor.createCharacters("\n"));
               first = false;
            }
            p.generate(constructor,dest);
            dest.send(constructor.createCharacters("\n"));
         }
      }
      dest.send(constructor.createElementEnd(XML.ROLE_NAME));
   }
}
